package com.jf.cloud.service.sysmanager.common.db;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.JdbcUtils;

import java.beans.PropertyDescriptor;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

/**
 * JDBC基础映射器
 * 
 * @author 程伟平 创建时间：2013-10-22 09:30:48
 */
public class BaseRowMapper<T> implements RowMapper<T> {

	/**
	 * 日志
	 */
	private static Log log = LogFactory.getLog(BaseRowMapper.class);

	/**
	 * 映射类
	 */
	private Class<T> mappedClass;

	/**
	 * 构造函数
	 */
	private BaseRowMapper(Class<T> mappedClass) {
		this.mappedClass = mappedClass;
	}

	public T mapRow(ResultSet rs, int rowNum) throws SQLException {
		// 实体
		T mappedObject = BeanUtils.instantiate(this.mappedClass);
		BeanWrapper beanWrapper = new BeanWrapperImpl(mappedObject);

		// 数据
		ResultSetMetaData rsmd = rs.getMetaData();
		int columnCount = rsmd.getColumnCount();
		for (int index = 1; index <= columnCount; index++) {
			// 字段名称
			String columnName = JdbcUtils.lookupColumnName(rsmd, index);
			// 属性名称
			String propertyName = getPropertyNameByCamelCase(columnName);
			// 属性描述器
			PropertyDescriptor pd = getPropertyDescriptor(beanWrapper, propertyName);
			if (pd != null) {
				// 设置属性值
				beanWrapper.setPropertyValue(pd.getName(), JdbcUtils.getResultSetValue(rs, index, pd.getPropertyType()));
			}
		}

		return mappedObject;
	}

	/**
	 * 根据字段名称获取属性名称 规则说明：驼峰命名法（CamelCase）
	 * 
	 * @author 程伟平 创建时间：2013-10-22 16:30:30
	 */
	private String getPropertyNameByCamelCase(String columnName) {
		StringBuffer sb = new StringBuffer();
		String[] words = columnName.split("_");
		for (String word : words) {
			// 第1个单词小写字母开始
			if (sb.length() == 0) {
				sb.append(word.toLowerCase());
			}
			// 第2个单词及以后每个单词的首字母都采用大写字母
			else {
				// 首字母大写
				sb.append(word.substring(0, 1).toUpperCase());
				// 非首字母小写
				sb.append(word.substring(1).toLowerCase());
			}
		}
		return sb.toString();
	}

	/**
	 * 根据属性名称获取属性描述器
	 * 
	 * @author 程伟平 创建时间：2013-11-10 17:50:30
	 */
	private PropertyDescriptor getPropertyDescriptor(BeanWrapper beanWrapper, String propertyName) {
		PropertyDescriptor propertyDescriptor = null;
		try {
			propertyDescriptor = beanWrapper.getPropertyDescriptor(propertyName);
		} catch (Exception e) {
			log.error("根据属性名称获取属性描述器出错了！", e);
		}
		return propertyDescriptor;
	}

	/**
	 * 实例化一个JDBC基础映射器
	 * 
	 * @author 程伟平 创建时间：2013-10-22 10:32:28
	 */
	public static <T> BaseRowMapper<T> newInstance(Class<T> mappedClass) {
		return new BaseRowMapper<T>(mappedClass);
	}

}
